<?php
/**
 * @copyright: ©2024 永州 微聚商网络科技有限公司
 * @link: https://www.wEijuyunke.com
 */
namespace app\mobile\controller;

use app\BaseController;
use think\App;
use think\facade\Request;
use think\facade\Db;
use think\facade\Log;
use think\Model;
use app\admin\model\FigureUser;
use app\admin\model\FigureFaceSwapImage;
use app\admin\model\FigureFaceSwapTask;
use app\common\service\ApiService;
use app\admin\model\FigureCloneSet;

/**
 * 视频换脸操作
 *
 * @author Administrator
 *        
 */
class Face extends BaseController
{

    /**
     * 人脸图片上传
     * http://aigc.weijuyunke.cn/mobile/face/imageAdd
     *
     * @param
     *            uid 用户id
     * @param
     *            face_url 人脸图片
     */
    public function imageAdd()
    {
        try {
            $uid = input('uid');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $face_url = input('face_url');
            if (empty($user)) {
                return result(- 1, 'face_url必传');
            }
            
            $data = array(
                'uid' => $uid,
                'face_url' => $face_url
            );
            
            $faceSwap = new FigureFaceSwapImage();
            $faceSwap->save($data);
            
            $apiService = new ApiService();
            $result = $apiService->faceImageAdd($face_url);
            
            if (isset($result['code']) && $result['code'] == 1) {
                $data = $result['data'];
                $faceSwap->save([
                    '_id' => $data
                ]);
                return result(0, '上传成功');
            } else {
                return result(- 1, $result['msg']);
            }
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 人脸图片列表
     * http://aigc.weijuyunke.cn/mobile/face/imageList
     *
     * @param
     *            uid 用户id
     * @param
     *            page 页码
     * @param
     *            psize 每页条数
     */
    public function imageList()
    {
        try {
            $uid = input('uid');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $list = FigureFaceSwapImage::where(" uid = {$uid} ")->order('create_time', 'desc')->select();
            if (empty($list)) {
                $list = array();
            }
            
            return result(0, 'success', $list);
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 人脸图片删除
     * http://aigc.weijuyunke.cn/mobile/face/imageDel
     *
     * @param
     *            uid 用户id
     * @param
     *            image_id 图片id
     */
    public function imageDel()
    {
        try {
            $uid = input('uid');
            $image_id = input('image_id');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $image = FigureFaceSwapImage::where([
                'uid' => $uid,
                'id' => $image_id
            ])->find();
            
            if (empty($image)) {
                return result(- 1, '图片不存在');
            }
            
            $image->delete();
            return result(0, '删除成功');
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 换脸预览
     * http://aigc.weijuyunke.cn/mobile/face/previewAdd
     *
     * @param
     *            uid 用户id
     * @param
     *            face_url 人脸图片
     * @param
     *            video_url 视频链接
     */
    public function previewAdd()
    {
        try {
            $uid = input('uid');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $face_url = input('face_url');
            if (empty($face_url)) {
                return result(- 1, 'face_url必传');
            }
            
            $video_url = input('video_url');
            if (empty($video_url)) {
                return result(- 1, 'video_url必传');
            }
            
            $apiService = new ApiService();
            $result = $apiService->facePreviewAdd([
                'face_url' => $face_url,
                'video_url' => $video_url
            ]);
            
            if (isset($result['code']) && $result['code'] == 1) {
                
                $data = $result['data'];
                return result(0, '上传成功', $data);
            } else {
                return result(- 1, $result['msg']);
            }
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 换脸预览状态
     * http://aigc.weijuyunke.cn/mobile/face/previewStatus
     *
     * @param
     *            id 预览id
     */
    public function previewStatus()
    {
        try {
            $id = input('id');
            if (empty($id)) {
                return result(- 1, 'id必传');
            }
            
            $apiService = new ApiService();
            $result = $apiService->facePreviewStatus($id);
            
            if (isset($result['code']) && $result['code'] == 1) {
                $data = $result['data'];
                return result(0, '查询成功', $data);
            } else {
                return result(- 1, $result['msg']);
            }
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 换脸生成
     * http://aigc.weijuyunke.cn/mobile/face/taskAdd
     *
     * @param
     *            uid 用户id
     * @param
     *            name 名称
     * @param
     *            face_url 人脸图片
     * @param
     *            video_url 视频链接
     */
    public function taskAdd()
    {
        try {
            $uid = input('uid');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $face_url = input('face_url');
            if (empty($face_url)) {
                return result(- 1, 'face_url必传');
            }
            
            $video_url = input('video_url');
            if (empty($video_url)) {
                return result(- 1, 'video_url必传');
            }
            
            $tally = sysconfig('tally', 'face_deduct');
            $duration = ceil(getDuration(2, $video_url));
            $money = $tally * $duration;
            
            if (! $user['is_member']) {
                if ($user['balance'] < $money) {
                    return result(- 2, '余额不足，请充值');
                }
            }
            
            $params = [
                'uid' => $uid,
                'face_url' => $face_url,
                'video_url' => $video_url
            ];
            
            if (! empty(input('name'))) {
                $params['name'] = input('name');
            }
            
            $log_no = getPayNo('FA');
            
            $set = FigureCloneSet::where("id", 1)->find();
            if (isset($set['face_check']) && $set['face_check'] == 1) {
                
                $faceTask = new FigureFaceSwapTask();
                $faceTask->save([
                    'log_no' => $log_no,
                    'uid' => $uid,
                    'name' => input('name'),
                    'face_url' => $face_url,
                    'video_url' => $video_url
                ]);
                
                user_balance_used($uid, $log_no, 2, 5, $duration);
                
                $faceTask->save([
                    'is_status' => 1,
                    'current_status' => 'initialized'
                ]);
                return result(0, '上传成功，等待审核');
            } else {
                $apiService = new ApiService();
                $result = $apiService->faceTaskAdd([
                    'name' => input('name'),
                    'face_url' => $face_url,
                    'video_url' => $video_url
                ]);
                
                if (isset($result['code']) && $result['code'] == 1) {
                    
                    $faceTask = new FigureFaceSwapTask();
                    $faceTask->save([
                        'log_no' => $log_no,
                        'uid' => $uid,
                        'name' => input('name'),
                        'face_url' => $face_url,
                        'video_url' => $video_url
                    ]);
                    
                    user_balance_used($uid, $log_no, 2, 5, $duration);
                    
                    $faceTask->save([
                        '_id' => $result['data']['id'],
                        'current_status' => $result['data']['current_status'],
                        'duration' => $result['data']['duration']
                    ]);
                    
                    return result(0, '生成成功');
                } else {
                    
                    return result(- 1, $result['msg']);
                }
            }
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 换脸列表
     * http://aigc.weijuyunke.cn/mobile/face/taskList
     *
     * @param
     *            uid 用户id
     * @param
     *            name 名称
     * @param
     *            page 页码
     * @param
     *            psize 每页条数
     */
    public function taskList()
    {
        try {
            $uid = input('uid');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $pindex = max(1, intval(input('page')));
            $psize = empty(input('psize')) ? 10 : intval(input('psize'));
            
            $where = " uid = {$uid} ";
            
            if (! empty(input('name'))) {
                $name = input('name');
                $where .= " AND name LIKE '%{$name}%'";
            }
            
            if (! empty(input('current_status'))) {
                $current_status = input('current_status');
                
                if ($current_status == 'initialized') {
                    $where .= " AND (current_status = 'sent' OR current_status = 'initialized' OR current_status = 'processing') ";
                } else {
                    $where .= " AND current_status = '{$current_status}'";
                }
            }
            
            $total = FigureFaceSwapTask::where($where)->count();
            if ($total) {
                $list = FigureFaceSwapTask::where($where)->order('create_time', 'desc')
                    ->limit(($pindex - 1) * $psize, $psize)
                    ->select();
                
                // foreach ($list as $key => $value) {
                
                // $where = " type = 2 AND video_id = {$value['id']}";
                
                // $play = FigureVideoRepost::where($where)->sum('total_play');
                // $like = FigureVideoRepost::where($where)->sum('total_like');
                // $comment = FigureVideoRepost::where($where)->sum('total_comment');
                
                // $list[$key]['play'] = empty($play) ? 0 : $play;
                // $list[$key]['like'] = empty($like) ? 0 : $like;
                // $list[$key]['comment'] = empty($comment) ? 0 : $comment;
                // }
            } else {
                $list = array();
            }
            
            $totalPage = ceil($total / $psize);
            
            return result(0, 'success', array(
                'list' => $list,
                'total' => $total,
                'pindex' => $pindex,
                'psize' => $psize,
                'totalPage' => $totalPage
            ));
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 换脸删除
     * http://aigc.weijuyunke.cn/mobile/face/taskDel
     *
     * @param
     *            uid 用户id
     * @param
     *            task_id 换脸id
     */
    public function taskDel()
    {
        try {
            $uid = input('uid');
            $task_id = input('task_id');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $task = FigureFaceSwapTask::where([
                'uid' => $uid,
                'id' => $task_id
            ])->find();
            if (empty($task)) {
                return result(- 1, '换脸不存在');
            }
            
            if (! empty($task['local_url'])) {
                $urlTemp = explode("/", $task['local_url']);
                $urlName = end($urlTemp);
                
                $coverTemp = explode("/", $task['local_cover']);
                $coverName = end($coverTemp);
                
                $url_path = root_path() . 'public/uploads/face/' . $urlName;
                $cover_path = root_path() . 'public/uploads/face-cover/' . $coverName;
                
                if (is_file($url_path)) {
                    unlink($url_path);
                }
                if (is_file($cover_path)) {
                    unlink($cover_path);
                }
            }
            
            $task->delete();
            return result(0, '删除成功');
        } catch (\Exception $e) {
            return result(- 1, '异常' . $e->getLine() . "--->" . $e->getMessage());
            exit();
        }
    }

    /**
     * 下载视频
     * http://aigc.weijuyunke.cn/mobile/face/toLocal
     *
     * @param
     *            uid 用户id
     * @param
     *            task_id 换脸id
     */
    public function toLocal()
    {
        try {
            
            set_time_limit(0);
            ini_set("memory_limit", "1024M");
            ini_set('max_execution_time', 1000);
            
            $uid = input('uid');
            $task_id = input('task_id');
            
            $user = FigureUser::where('id', $uid)->find();
            if (empty($user)) {
                return result(- 1, '用户不存在');
            }
            
            $task = FigureFaceSwapTask::where([
                'uid' => $uid,
                'id' => $task_id
            ])->find();
            if (empty($task)) {
                return result(- 1, '换脸不存在');
            }
            if (empty($task['result_url'])) {
                return result(- 1, '换脸未生成成功');
            }
            
            if (! empty($task['local_url'])) {
                return result(0, 'success', [
                    'local_cover' => $task['local_cover'],
                    'local_url' => $task['local_url']
                ]);
            }
            
            $start = time();
            
            $name = time() . rand(999, 9999);
            
            $path = root_path() . 'public/uploads/face';
            
            if (! is_dir($path)) {
                mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
            }
            
            $path .= '/face-' . $name . '.mp4';
            
            // 使用cURL下载视频
            $ch = curl_init($task['result_url']);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            $videoData = curl_exec($ch);
            curl_close($ch);
            
            // 将视频数据保存到本地文件
            $videoFile = fopen($path, 'wb');
            fwrite($videoFile, $videoData);
            
            fclose($videoFile);
            
            $domain = request()->domain();
            $paths = $domain . "/uploads/face/face-" . $name . '.mp4';
            
            $cover_path = root_path() . 'public/uploads/face-cover';
            
            if (! is_dir($cover_path)) {
                mkdir(iconv("UTF-8", "GBK", $cover_path), 0777, true);
            }
            
            $cover_path .= '/face-cover-' . $name . '.jpg';
            
            $ch = curl_init($task['result_url'] . "?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            $coverData = curl_exec($ch);
            curl_close($ch);
            
            // 将视频数据保存到本地文件
            $coverFile = fopen($cover_path, 'wb');
            fwrite($coverFile, $coverData);
            
            fclose($coverFile);
            
            $domain = request()->domain();
            $cover = $domain . "/uploads/face-cover/face-cover-" . $name . '.jpg';
            
            $task->save([
                'is_local' => 1,
                'local_url' => $paths,
                'local_cover' => $cover,
                'local_time' => time()
            ]);
            
            $end = time();
            return result(0, 'success', [
                'start' => $start,
                'end' => $end,
                'local_cover' => $cover,
                'local_url' => $paths
            ]);
        } catch (\Exception $e) {
            Log::write("toLocal 失败" . json_encode($e->getTrace()), 'info');
            return result(- 1, '操作异常:' . $e->getMessage(), $e->getTrace());
        }
    }

    /**
     * 换脸视频详情
     * http://aigc.weijuyunke.cn/mobile/face/videoDetail
     *
     * @param
     *            video_id 视频id
     */
    public function videoDetail()
    {
        try {
            
            set_time_limit(0);
            ini_set("memory_limit", "1024M");
            ini_set('max_execution_time', 1000);
            
            $task_id = input('video_id');
            
            $task = FigureFaceSwapTask::where('id', $task_id)->find();
            if (empty($task)) {
                return result(- 1, '换脸不存在');
            }
            if (empty($task['result_url'])) {
                return result(- 1, '换脸未生成成功');
            }
            
            if (! empty($task['local_url'])) {
                return result(0, 'success', $task);
            }
            
            $start = time();
            
            $name = time() . rand(999, 9999);
            
            $path = root_path() . 'public/uploads/face';
            
            if (! is_dir($path)) {
                mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
            }
            
            $path .= '/face-' . $name . '.mp4';
            
            // 使用cURL下载视频
            $ch = curl_init($task['result_url']);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            $videoData = curl_exec($ch);
            curl_close($ch);
            
            // 将视频数据保存到本地文件
            $videoFile = fopen($path, 'wb');
            fwrite($videoFile, $videoData);
            
            fclose($videoFile);
            
            $domain = request()->domain();
            $paths = $domain . "/uploads/face/face-" . $name . '.mp4';
            
            $cover_path = root_path() . 'public/uploads/face-cover';
            
            if (! is_dir($cover_path)) {
                mkdir(iconv("UTF-8", "GBK", $cover_path), 0777, true);
            }
            
            $cover_path .= '/face-cover-' . $name . '.jpg';
            
            $ch = curl_init($task['result_url'] . "?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            $coverData = curl_exec($ch);
            curl_close($ch);
            
            // 将视频数据保存到本地文件
            $coverFile = fopen($cover_path, 'wb');
            fwrite($coverFile, $coverData);
            
            fclose($coverFile);
            
            $domain = request()->domain();
            $cover = $domain . "/uploads/face-cover/face-cover-" . $name . '.jpg';
            
            $task->save([
                'is_local' => 1,
                'local_url' => $paths,
                'local_cover' => $cover,
                'local_time' => time()
            ]);
            
            return result(0, 'success', $task);
        } catch (\Exception $e) {
            Log::write("videoDetail 失败" . json_encode($e->getTrace()), 'info');
            return result(- 1, '操作异常:' . $e->getMessage(), $e->getTrace());
        }
    }
}